package ecom.shell.commandsImpl;

import ecom.beans.exception.DeviseException;
import ecom.shell.exception.InsuffisantPrivilegeException;
import ecom.beans.EcomAdminRemote;
import ecom.beans.EcomCustomerRemote;
import ecom.beans.StockBean;
import ecom.shell.commandsImpl.OutputCommandImpl.Outputs;
import java.io.IOException;
import java.io.PrintStream;
import java.io.StringWriter;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import shell.ShellCommand;
import shell.ShellContext;

public class StockCommandImpl implements ShellCommand {

    private ShellContext _context = null;

    public StockCommandImpl(ShellContext context) {
        _context = context;
    }

    @Override
    public String getName() {
        return "stock";
    }

    @Override
    public String getUsage() {
        return "stock";
    }

    @Override
    public String getShortDescription() {
        String description = "Stock commands\n";
        description += "\t-help ......................................................get stock commands description\n";
        if (true == _context.getVar("isAdmin")) {
            description += "\t-add [productstore id] [product id] [quantity] [price] .....add stock\n";
            description += "\t-remove [productstore id] [product id] .....................remove stock\n";
            description += "\t-update [productstore id] [product id] [quantity] ..........update stock quantity\n";
        }
        description += "\t-id [productstore id] [product id] .........................display specified stock details\n";
        return description;
    }

    @Override
    public String execute(String cmdline, PrintStream out, PrintStream err) throws InsuffisantPrivilegeException {
        StringBuilder res = new StringBuilder();
        EcomCustomerRemote ecomCustomerBean = (EcomCustomerRemote) _context.getVar("customerBean");
        EcomAdminRemote ecomAdminBean = (EcomAdminRemote) _context.getVar("adminBean");
        Outputs currentOutput = (Outputs) _context.getVar("output");
        String currentCurrency = (String) _context.getVar("currency");

        Set<StockBean> stocksList = null;

        StringTokenizer st = new StringTokenizer(cmdline, " ");

        st.nextToken();

        if (st.countTokens() == 0) {
            stocksList = ecomAdminBean.getAllStocks(null);
            try {
                return printList(out, stocksList, currentOutput, ecomCustomerBean, currentCurrency);
            } catch (Exception ex) {
                System.err.println("Error with getting all stocks : " + ex.getMessage());
            }
        } else {
            String option = st.nextToken();

            if (option.equals("-help")) {
                res.append(getShortDescription());
            } else if (option.equals("-add")) {
                if (true != _context.getVar("isAdmin")) {
                    throw new InsuffisantPrivilegeException();
                }
                if (st.countTokens() == 4) {
                    try {
                        Long idProductstore = Long.valueOf(st.nextToken());
                        Long idProduct = Long.valueOf(st.nextToken());
                        Integer quantity = Integer.valueOf(st.nextToken());
                        Double price = Double.valueOf(st.nextToken());

                        ecomAdminBean.createStock(idProductstore, idProduct, quantity, price);
                        res.append("Stock created");
                    } catch (NumberFormatException ex) {
                        err.println("The idProductstore,idProduct,quantity,price must be a number");
                    } catch (Exception ex) {
                        err.println("Error with stock creation : " + ex.getMessage());
                    }
                } else {
                    err.println(EcomCommandsConstantes.INCORRECT_NUMBER_ARGS);
                }
            } else if (option.equals("-remove")) {
                if (true != _context.getVar("isAdmin")) {
                    throw new InsuffisantPrivilegeException();
                }
                if (st.countTokens() == 2) {
                    try {
                        Long idProductstore = Long.valueOf(st.nextToken());
                        Long idProduct = Long.valueOf(st.nextToken());
                        ecomAdminBean.removeStock(idProductstore, idProduct);
                        res.append("Stock deleted");
                    } catch (NumberFormatException ex) {
                        err.println("The idProductstore,idProduct must be a number");
                    } catch (Exception ex) {
                        err.println("Error with stock remove : " + ex.getMessage());
                    }
                } else {
                    err.println(EcomCommandsConstantes.INCORRECT_NUMBER_ARGS);
                }
            } else if (option.equals("-update")) {
                if (true != _context.getVar("isAdmin")) {
                    throw new InsuffisantPrivilegeException();
                }
                if (st.countTokens() == 3) {
                    try {
                        Long idProductstore = Long.valueOf(st.nextToken());
                        Long idProduct = Long.valueOf(st.nextToken());
                        Integer quantity = Integer.valueOf(st.nextToken());

                        ecomAdminBean.updateStockQuantity(idProductstore, idProduct, quantity);
                        res.append("Stock updated");
                    } catch (NumberFormatException ex) {
                        err.println("The idProductstore,idProduct,quantity must be a number");
                    } catch (Exception ex) {
                        err.println("Error with stock updated : " + ex.getMessage());
                    }
                } else {
                    err.println(EcomCommandsConstantes.INCORRECT_NUMBER_ARGS);
                }
            } else if (option.equals("-id")) {
                if (st.countTokens() == 2) {
                    try {
                        Long idProductstore = Long.valueOf(st.nextToken());
                        Long idProduct = Long.valueOf(st.nextToken());
                        StockBean stock = ecomCustomerBean.getStockByIdProductstoreAndIdProduct(idProductstore, idProduct);
                        return printStore(out, stock, currentOutput, ecomCustomerBean, currentCurrency);
                    } catch (NumberFormatException ex) {
                        err.println("The idProductstore,idProduct must be a number");
                    } catch (Exception ex) {
                        err.println("Error with stock detail : " + ex.getMessage());
                    }
                } else {
                    err.println(EcomCommandsConstantes.INCORRECT_NUMBER_ARGS);
                }
            } else {
                err.println(option + " is not known for stock command");
            }
        }
        return res.toString();
    }

    private String printList(PrintStream out, Set<StockBean> stockList, Outputs currentOutput, EcomCustomerRemote ecomCustomerBean, String currentCurrency) throws DeviseException, IOException {
        StringBuilder res = new StringBuilder();
        if (currentOutput.equals(Outputs.XML)) {
            Element stockE = new Element("stocks");
            org.jdom.Document document = new Document(stockE);
            for (StockBean stock : stockList) {
                stockE.addContent(buildXMLStoreNode(stock, ecomCustomerBean, currentCurrency));
            }
            XMLOutputter sortie = new XMLOutputter(Format.getPrettyFormat());
            return sortie.outputString(document);
        } else if (currentOutput.equals(Outputs.TEXT)) {
            for (StockBean stock : stockList) {
                res.append(printTEXT(out, stock, currentCurrency)).append("\n");
            }
        } 
        else {
            res.append("Output format '").append(currentOutput).append("' is not implementing for this command");
        }
        return res.toString();
    }

    private String printStore(PrintStream out, StockBean stock, Outputs currentOutput, EcomCustomerRemote ecomCustomerBean, String currentCurrency) throws DeviseException, IOException {
        Set<StockBean> stocks = new HashSet<StockBean>();
        stocks.add(stock);
        return printList(out, stocks, currentOutput, ecomCustomerBean, currentCurrency);
    }

    private String printTEXT(PrintStream out, StockBean stock, String currentCurrency) {
        return (stock.toString() + " IN " + currentCurrency);
    }

    public static Element buildXMLStoreNode(StockBean stock, EcomCustomerRemote ecomCustomerBean, String currentCurrency) throws DeviseException {
        Element stockE = new Element("stock");

        Element idProductstore = new Element("idProductstore");
        idProductstore.setText(stock.getProductstoreBean().getIdProductStore().toString());
        stockE.addContent(idProductstore);

        Element idProduct = new Element("idProduct");
        idProduct.setText(stock.getProductBean().getIdProduct().toString());
        stockE.addContent(idProduct);

        Element quantity = new Element("quantity");
        quantity.setText(stock.getQuantity().toString());
        stockE.addContent(quantity);

        Element price = new Element("price");
        price.setText(stock.getPrice().toString());
        stockE.addContent(price);

        return stockE;
    }

  
}
